<template>
  <div id="map">

  </div>
</template>

<script setup>
import mapboxgl from "mapbox-gl";
import MapboxLanguage from '@mapbox/mapbox-gl-language'; //可以将标签改为中文
import {onMounted, reactive} from "vue";

let map;
onMounted(() => {
  mapboxgl.accessToken = 'pk.eyJ1IjoibWFwYm94ZGV2dXNlcjUyMCIsImEiOiJjbHFrb2w3M2IyNHB2MnFtZWx1ZzFjNHZmIn0.CMoLsalSeXlJiLBNyUK1nA'
  // init map
  map = new mapboxgl.Map({
    container: 'map', // 地图容器id
    style: 'mapbox://styles/mapbox/streets-v12', // 地图样式
    center: {lng: 119, lat: 34.3}, // 地图初始中心
    zoom: 12, // 地图初始缩放级别
    projection: 'globe', // 地图投影为3D
    pitch: 32, // 相对于地图3D视角的角度
    essential: true,
    antialias: true,
    renderWorldCopies: false, //可理解为loop，在projection: 'globe'时无效
    skipOnboarding: true,//可选择不等待瓦片加载
  })
  // Add a scale control(缩放控制插件) to the map
  map.addControl(new mapboxgl.ScaleControl());
  // Mapbox汉化处理
  map.addControl(new MapboxLanguage({
    defaultLanguage: 'zh-Hans'
  }));

  map.on('load', () => {
    add3DModel();
  })
})

const add3DModel = () => {
  // parameters to ensure the model is georeferenced correctly on the map
  const modelOrigin = [119, 34.3];
  const modelAltitude = 0;
  const modelRotate = [Math.PI / 2, 0, 0];
  // set the model's position by build MeractorCoordinate
  const modelAsMercatorCoordinate = mapboxgl.MercatorCoordinate.fromLngLat(
    modelOrigin,
    modelAltitude,
  )

  // transformation parameters to position, rotate and scale the 3D model onto the map
  const modelTransform = {
    translateX: modelAsMercatorCoordinate.x,
    translateY: modelAsMercatorCoordinate.y,
    translateZ: modelAsMercatorCoordinate.z,
    rotateX: modelRotate[0],
    rotateY: modelRotate[1],
    rotateZ: modelRotate[2],
    // 将3D Model模型的大小根据MercatorCoordinate单位进行缩放转换
    scale: modelAsMercatorCoordinate.meterInMercatorCoordinateUnits()
  };

  const customLayer = {
    id: '3d-model',
    type: 'custom',
    renderingMode: '3d',
    onAdd: function (map, gl) {
      this.camera = new THREE.Camera();
      this.scene = new THREE.Scene();

// create two three.js lights to illuminate the model
      const directionalLight = new THREE.DirectionalLight(0xffffff);
      directionalLight.position.set(0, -70, 100).normalize();
      this.scene.add(directionalLight);

      const directionalLight2 = new THREE.DirectionalLight(0xffffff);
      directionalLight2.position.set(0, 70, 100).normalize();
      this.scene.add(directionalLight2);

// use the three.js GLTF loader to add the 3D model to the three.js scene
      const loader = new THREE.GLTFLoader();
      loader.load(
        'https://docs.mapbox.com/mapbox-gl-js/assets/34M_17/34M_17.gltf',
        (gltf) => {
          this.scene.add(gltf.scene);
        }
      );
      this.map = map;

// use the Mapbox GL JS map canvas for three.js
      this.renderer = new THREE.WebGLRenderer({
        canvas: map.getCanvas(),
        context: gl,
        antialias: true
      });

      this.renderer.autoClear = false;
    },
    render: function (gl, matrix) {
      const rotationX = new THREE.Matrix4().makeRotationAxis(
        new THREE.Vector3(1, 0, 0),
        modelTransform.rotateX
      );
      const rotationY = new THREE.Matrix4().makeRotationAxis(
        new THREE.Vector3(0, 1, 0),
        modelTransform.rotateY
      );
      const rotationZ = new THREE.Matrix4().makeRotationAxis(
        new THREE.Vector3(0, 0, 1),
        modelTransform.rotateZ
      );

      const m = new THREE.Matrix4().fromArray(matrix);
      const l = new THREE.Matrix4()
        .makeTranslation(
          modelTransform.translateX,
          modelTransform.translateY,
          modelTransform.translateZ
        )
        .scale(
          new THREE.Vector3(
            modelTransform.scale,
            -modelTransform.scale,
            modelTransform.scale
          )
        )
        .multiply(rotationX)
        .multiply(rotationY)
        .multiply(rotationZ);

      this.camera.projectionMatrix = m.multiply(l);
      this.renderer.resetState();
      this.renderer.render(this.scene, this.camera);
      this.map.triggerRepaint();
    }
  }
}
</script>

<style lang="scss" scoped>
#map {
  height: 100vh;
  width: 100%;
}
</style>

<!--https://docs.mapbox.com/mapbox-gl-js/example/add-3d-model/-->
